package langen;
import utils.WordNetWrapper;
import net.didion.jwnl.data.POS;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import net.didion.jwnl.data.Word;
/**
 * <b>this class is used to generate the language template. it implements an interface which botchat uses to realize itself talkable.
 * <p>class frame is made by School of Informatics and detailed implement is accomplished by Hao Wang. 
 * 
 */
public class TemplateLanguageGenerator  implements  LanguageGenerator{
    public static Random P=new Random();
    
    /**
     * A collection of sentence templates which this language generator can use
     */
    private ArrayList <SentenceTemplate> sentenceList  = new ArrayList <SentenceTemplate> ();
    
    /**
     * create a object of wordnetwrapper for class use to speed up the programme.
     */
    
    private WordNetWrapper word=new WordNetWrapper();
    
    private HashMap keywords=new HashMap();

    

    /**
     * Creates a TemplateLanguageGenerator, sets up the sentence templates,
     *  TemplateLanguageGenerator will be used by chatbot as a talk frame 
     *
     *
     */
    public TemplateLanguageGenerator() {
        populateSentences();
        populatekeywords();
        
    }

    /**
     * Sets up the sentence templates which can be used by this language generator.
     * 
     * contents of sentence templates are made by author.
     * template format contains two parts and you can find format detail in class sentence template.
     * canned text and the instructions are seprated by '%'
     *
     */
    private void populateSentences() {
        /*add sentences to sentencetemplate*/
       sentenceList.add(new SentenceTemplate("question","do you like %NOUN% or %NOUN%?"));
       sentenceList.add(new SentenceTemplate("reply","i like %NOUN%. What about you? %ADJECTIVE% %NOUN% or something else."));
       sentenceList.add(new SentenceTemplate("reply","most people think %ADJECTIVE% is better than %ADJECTIVE%."));
       sentenceList.add(new SentenceTemplate("reply","i can %VERB% the %NOUN%."));
       sentenceList.add(new SentenceTemplate("question","How about change a topic coures or university or %NOUN% or %NOUN% or %VERB% or %VERB% or whatever you like."));
        
    }
    private void populatekeywords(){
       
       keywords.put("friend", "I don't see your friend, how about go to other place?");
       keywords.put("hello", "hello, welcome to you, enjoy yourself");
       keywords.put("know", "I am very very busy");
       keywords.put("where", "Edinburgh is a very beautiful city");
       keywords.put("I", "Your friend just left, what a pity!");
       keywords.put("you", "Thank you. The same to you");
        
    }

    

    /**
     * Generates a sentence using a randomly chosen template.
     *
     * @return A string containing the sentence
     */

    public String generateSentence() {
   
    int pick=P.nextInt(sentenceList.size());//set the the max int is 4 and mim is 0 because the list contains 5 elements.
    String get;
      
      get=this.expandTemplate(sentenceList.get(pick).getTemplate());//get the random sentence,set flag=aa bb cc
     
        
         return get;
        
        
        
    }
    
    /**
     *a method for testing the expendtemplate.
     *actually we cannot call a private method in the test class, so we create a meathod of public to redirect the private expendtemplate.
     *
     *
     * @param sentenceTemplate The template which wants to be tested
     * 
     * @return A string containing the sentence expanded out of the template
     */
    public String test_expandTemplate(String sentenceTemplate)
    {
        return expandTemplate(sentenceTemplate);
    }
    
    
     /**
     * Expands the template into a full sentence. The templates are strings
     * consisting of canned text and instructions to generate more text. Canned
     * segments and instructions are delimited by "%".
     * <p>This method also works for expend template topic. If the remark='aa bb cc' it will generate a sentence other it will expend topic
     *
     ** @param sentenceTemplate The template which will be expanded
     * 
     * @return A string containing the sentence expanded out of the template
     */
    
  protected String expandTemplate(String sentenceTemplate) {
        
      String[] parts=sentenceTemplate.split("%");
      String expanded_template="";
      for(String part: parts){
          if(part.equals("NOUN"))
                expanded_template+=word.getNounAtRandom()+" ";
             else if(part.equals("VERB"))
                expanded_template+=word.getVerbAtRandom()+" ";
             else if(part.equals("ADJECTIVE"))
                expanded_template+=word.getAdjectiveAtRandom()+" ";
          else
            expanded_template+=part+" ";
        }
        return expanded_template;
    }

     protected String stip(String w){
        ArrayList<String> punctuations=new ArrayList<String>();
        punctuations.add(",");
        punctuations.add(".");
        punctuations.add("?");
        punctuations.add("!");
        for(String punctuation:punctuations)
        {

            w= w.replace(punctuation, "");
        }
        return w;
    }
    
    /**
     * Use key word matching to generate a canned response to the specified
     * comment.
     * Due to the key word range is very very limited so the meathod defines that if it cannot find keywordmatch the method will call expendtemplateTopic
     *  instead to guarantee the conversation sense.
     *  
     * @param remark The input which we must respond to
     * 
     * @return A string containing a reply to the specified remark
     */
    private String keyWordMatch(String remark){
       remark=this.stip(remark.toLowerCase());

       String[] words=remark.split(" "); 
       String s;
       for(String word: words){
           if(keywords.containsKey(word))
           {
               return (String) keywords.get(word);
           }
           
       }
       
              
            s=this.findKeyWord(remark);
            return this.expandTemplateTopic(s,sentenceList.get(P.nextInt(sentenceList.size())).getTemplate());
          
    }

       

   
          



 
    
    /**
     *a method for testing the keywordmath. 
     *
     * actually we cannot call a private method in the test class, so we create a meathod of public to redirect the private keywordmatch().
     * 
     * @param remark The input which we must respond to
     * @return A string containing a reply to the specified remark
     */
     public String keyWordMatchWrapper(String remark) {
         
    return keyWordMatch(remark);    
}

    /**
     * Parse the input remark, and find a key word which we can respond to
     * 
     * @param remark The input to be parsed
     * 
     * @return A keyword from the input which will be used in the reply
     */
    
   
    
    
    protected String findKeyWord(String remark) {
        remark=this.stip(remark);
       
             String[] find=remark.split(" ");//split a sentence by ' '.
             

             ArrayList<String> aList = new ArrayList<String>();



             for(String w: find)
             {
                 
                 
                 if(word.isNoun(w))
                      aList.add(w);
                 else if(word.isAdjective(w))
                     aList.add(w);
                 else if(word.isVerb(w))
                     aList.add(w);
             }
             int i=P.nextInt(aList.size());

             return aList.get(i);
                     
                 
             


             
    }
    
     /**
     *a method for testing the findkeyword. 
     *
     * actually we cannot call a private method in the test class, so we create a meathod of public to redirect the private keywordmatch().
     * 
     * @param remark a sentence we should find the key word
     * @return A word is considered as keyword
     */
    public String test_findkeyword(String remark)
    {

        return this.findKeyWord(remark);
    }
    
      /**
     *a method for testing the expendTemplateTopic. 
     *
     * actually we cannot call a private method in the test class, so we create a meathod of public to redirect the private keywordmatch().
     * 
     * @param a keyword we get 
     * @return A sentence based on the keyword
     */
    
    

    
    
    
    /**
     * Parse the input remark, and find a key word which we can respond to
     * 
     * @param remark The input to be parsed
     * 
     * @return A keyword from the input which will be used in the reply
     */
protected String expandTemplateTopic(String remark,String template){

    POS pos=this.getPos(remark);
    if(pos==null)
    {
        return this.expandTemplate(template);
    }
        List synonyms = word.getSynonyms(pos, remark);
        if (synonyms.size() == 0)
        {
            // Wordnet returns no synonyms for keyword, fall back on
            // expandTemplate.
            return expandTemplate(template);
        }

        /*
            Expand the sentence template, replacing %NOUN%, %ADJECTIVE% and %VERB%
            with randomly chosen synonyms of the keyword where possible, and simply
            randomly chosen nouns, adjectives and verbs elsewhere.
            (e.g. if the keyword is a noun, then all of its synonyms are nouns,
            so %NOUN% can be replaced with a synonym but %ADJECTIVE% and %VERB%
            cannot.)
            */
        String[] parts = template.split("%");
        String expanded_template = "";
        for (String part : parts) {
            if (part.equals("NOUN")) {
                if (pos == POS.NOUN)
                {
                    expanded_template += synonyms.get(P.nextInt(synonyms.size()));
                }
                else
                {
                    expanded_template += word.getNounAtRandom();
                }
            } else if (part.equals("VERB")) {
                if (pos == POS.VERB)
                {
                    expanded_template += synonyms.get(P.nextInt(synonyms.size()));
                }
                else
                {
                    expanded_template += word.getVerbAtRandom();
                }

            } else if (part.equals("ADJECTIVE")) {
                if (pos == POS.ADJECTIVE)
                {
                    expanded_template += synonyms.get(P.nextInt(synonyms.size()));
                }
                else
                {
                    expanded_template += word.getAdjectiveAtRandom();
                }
            } else {
                expanded_template += part;
            }
        }
        return expanded_template;
    }


    
    
    private POS getPos(String remark){
        if(word.isAdjective(remark))
        return POS.ADJECTIVE;
        else if(word.isNoun(remark))
            return POS.NOUN;
        else if(word.isVerb(remark))
            return POS.VERB;
        else{
      

            return null;

        }


    }
    

    /**
     * Generate a reply to the specified remark. The reply is related to the 
     * input remark in the vague sense that it contains a word relating to one 
     * of the words in the input. 
     * First of all, it calls findkeyword which returns the keyword of the sentence,then it randomly calls expendtemplatetopic or keywordmatch 
     * to generate a reply,then return the completed sentence
     *  
     * @param remark The remark which must be responded to
     * 
     * @return A string containing a response to the specified remark
     */
    
    public String generateReply(String remark) {
        String keyword; 
        keyword=this.findKeyWord(remark);
        
        if(false)
        return this.expandTemplateTopic(keyword,sentenceList.get(P.nextInt(sentenceList.size())).getTemplate());//if i==0 use expendtemplatetopic
        else
        {
            return this.keyWordMatch(remark);//i==1 use keywrodmatch
        }
}
    
   

}
